/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package GPSMapper;

import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.location.*;
import sUtils.*;
/**
 *
 * @author thomas.s
 */

public class GPSMap extends Canvas {

    Vector p = new Vector(16,4);
    Vector way = new Vector(1024,1024);
    GPSPoint lastWay = null;
    Coordinates lastC = null;
    boolean first=true;
    double minLat,minLon,maxLat,maxLon,lastLat=0,lastLon=0,diffLat=0,diffLon=0, chkLat=0, chkLon=0;
    float lastAlt=0;
    double xMeter=1,yMeter=1,scale=1000;
    boolean inScale=false, inMove = true;
    int x0=0,y0=0, ox,oy;
    public float course=0;
    long lastPressed=0;
    boolean dark=true;



    public GPSMap()
    {
        Coordinates c0 = new Coordinates(12.00,51.00,100);
        double distX = c0.distance( new Coordinates(12.00,51.01,100));
        double distY = c0.distance( new Coordinates(12.01,51.00,100));
        xMeter = 0.01/distX;
        yMeter = 0.01/distY;
    }

    public boolean addPoint( double lon, double lat, float alt, String name )
    {
        if (lon==0 && lat==0) return false;
        
        if (name.equalsIgnoreCase("Way"))
        {
            diffLon=lon-lastLon;
            diffLat=lat-lastLat;
            lastLon=lon;
            lastLat=lat;
            lastAlt=alt;
            lastC = new Coordinates(lat,lon,alt);

            if (lastWay!=null)
            {
                double dLon = Math.abs(chkLon-lon);
                double dLat = Math.abs(chkLat-lat);
                if (dLon<xMeter*20 && dLat<yMeter*20)
                {
                    lastWay.lat = lat;
                    lastWay.lon = lon;
                    lastWay.alt = alt;
                    if (dLon>xMeter*2 || dLat>yMeter*2) repaint();
                    return false;
                }
            }
            chkLat = lat;
            chkLon = lon;
            way.addElement( lastWay = new GPSPoint(lon,lat,alt,null) );
        }
        else p.addElement( new GPSPoint(lon,lat,alt,name) );

        if (first) { minLat=maxLat=lat; minLon=maxLon=lon; first=false; } else
        {
            if (lat<minLat) minLat=lat; else if (lat>maxLat) maxLat=lat;
            if (lon<minLon) minLon=lon; else if (lon>maxLon) maxLon=lon;
        }

        repaint();
        return true;
    }

    public void paint( Graphics g )
    {
        int w = getWidth();
        int h = getHeight();
        int x,y,ox=w/2,oy=h/2,col=0;
        boolean ob=false,b;
        long d, time=System.currentTimeMillis();
        GPSPoint pt=null;
        String s;

        // calc max scale:

        double f = lastLon-minLon;
        double f2 = maxLon-lastLon;
        if (f2>f) f=f2;
        f2 = lastLat-minLat;
        if (f2>f) f=f2;
        f2 = maxLat-lastLat;
        if (f2>f) f=f2;
        f/=xMeter;

        // calc scale:
        double fs = scale;
        if (fs>f) fs=f;
        double fx = ((double)((w-10)/2))/(fs*xMeter);
        double fy = -((double)((h-120)/2))/(fs*yMeter);
        Font fnt = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,Font.SIZE_SMALL);

        int x1 = 5, x2 = w-5, y1 = 60, y2 = h-60;

        g.setColor(dark ? 0 : 0xffffff);
        g.fillRect(0,30,w,h-60);

        g.setColor(dark ? 0x808040 : 0xa0a080 );
        x=w/2+x0;
        y=h/2+y0;
        ox = x + (int)(Math.sin(course*Math.PI/180.0)*400);
        oy = y + (int)(-Math.cos(course*Math.PI/180.0)*400);
        g.drawLine(ox, oy, x, y);
        
        int size = (int)(f);
        int scal = (int)(scale);
        for ( int i=0; i<way.size(); i++ ) {
            pt = (GPSPoint)(way.elementAt(i));
            x = pt.normLon(lastLon, fx )+w/2+x0;
            y = pt.normLat(lastLat, fy )+h/2+y0;

            b=(x>=x1 && x<x2 && y>=y1 && y<y2);
            if ( (b || ob) && i>0)
            {
                d = 255 - (pt.getDeltaTime(time))/(30*60000/255);
                if (d>-128)
                {
                    if (d<128) col=(int)((d<-128)?0:(d+128)); else
                    col=(int)(d&0xff) + (int)(((d-128)*2)<<16)+ (int)(((d/2))<<8);
                    if (col>0)
                    {
                        g.setColor(dark ? col : (0xffffff-col));
                        g.drawLine(ox, oy, x, y);
                    }
                }
            }
            ox=x;oy=y;ob=b;
        }

        g.setColor(dark ? 0xffff00 : 0x404080);
        for ( int i=0; i<p.size(); i++ ) {
            pt = (GPSPoint)(p.elementAt(i));
            x = pt.normLon(lastLon, fx )+w/2+x0;
            y = pt.normLat(lastLat, fy )+h/2+y0;
            g.drawArc( x-2, y-2, 5, 5, 0, 360 );
            g.drawArc( x-4, y-4, 9, 9, 0, 360 );
            if (lastC!=null)
            {
                int dist = (int)(new Coordinates(pt.lat,pt.lon,pt.alt).distance(lastC));
                s = pt.name + " " + dist;
                g.drawString(s,(x<w/2?0:-fnt.stringWidth(s))+x,(y<h/2?0:-fnt.getHeight())+y,0);
            }
        }

   // Pos:
        g.setColor(dark ? 0xffffff : 0);
        x=w/2+x0;
        y=h/2+y0;
        g.drawRect(x-5, y, 11, 1);
        g.drawRect(x, y-5, 1, 11);

   // Infos:
        g.setColor(0x202020);
        g.fillRect(0,0,w,30);
        g.fillRect(0,670,w,h-670);
        g.setColor(first?0xc06060:0x8080f0);
        g.setFont( fnt );

        s = Strings.getGPS_GMS( lastLat, 'N', 'S' ) + "   " +
             Strings.getGPS_GMS( lastLon, 'E', 'W' ) + "  " +
             Strings.toStr( course, 4, 1, ' ', "","°");
        g.drawString(s,0,0,0);
        s = "Points: " + way.size() + ", Scale: "+scal+"m / "+size+"m";
        g.drawString(s,0,670,0);

    }

    protected void pointerPressed( int x, int y )
    {
        inScale = false;
        inMove = false;
        if ( (System.currentTimeMillis() - lastPressed)<300 )
        {
            dark = !dark; repaint();
        }
        
        lastPressed = System.currentTimeMillis();

        inScale = (y>=630 && y<700);
        inMove = (y>=60 && y<630);
        if (y<60) x0=y0=0;
        ox=x; oy=y;
    }

    protected void pointerDragged( int x, int y )
    {
        if (inScale)
        {
            x = (x*10)/480;
            if (x<1) scale=10; else
            if (x<2) scale=50; else
            if (x<3) scale=100; else
            if (x<4) scale=250; else
            if (x<5) scale=500; else
            if (x<6) scale=1000; else
            if (x<7) scale=2000; else
            if (x<8) scale=5000; else
            if (x<9) scale=10000; else
            scale=100000;
            x0=y0=0;
            repaint();
        }
        if (inMove)
        {
            ox-=x; oy-=y;
            x0-=ox; y0-=oy;
            ox=x; oy=y;
            repaint();
        }
    }
}
